-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core: use new OpenCensus stats/tagging API. #3647
Conversation
Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok for us to run on our infrastructure. |
Thank you for your pull request. Before we can look at your contribution, we need to ensure all contributors are covered by a Contributor License Agreement. After the following items are addressed, please respond with a new comment here, and the automated system will re-verify.
Regards, |
testing Linux Foundation CLA |
1 similar comment
testing Linux Foundation CLA |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small-lish comments. The Census API looks good.
Technically this is a breaking behavioral change, because gRPC now handles a different type of Context key. However, it's unlikely that any 3rd-party has done any work on the old Census API. So this should fine.
StatsRecorder statsRecorder = | ||
this.statsRecorder != null ? this.statsRecorder : Stats.getStatsRecorder(); | ||
// // TODO: How do we check whether stats is enabled, now that the StatsRecorder is always | ||
// // non-null? Uncommenting this line causes test failures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most tests pass in the fake implementations from StatsTestUtils
, but Stats.getState()
returns DISABLED
. If you don't initialize CensusStatsModule
, these tests will fail.
A possibly better approach, is to make CensusStatsModule
public, and change the three-argument Census impl setter of the builder to overrideCensusStatsModule(CensusStatsModule)
. Tests will create CensusStatsModule
out of the impls from StatsTestUtils
, and here you can do:
if (statsEnabled) {
CensusStatsModule censusStats = this.censusStatsOverride;
if (censusStats == null && Stats.getStats() == StatsCollectionState.ENABLED) {
CensusStatsModule censusStats =
new CensusStatsModule(...);
}
if (censusStats != null) {
tracerFactories.add(censusStats.getServerTracerFactory());
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhangkun83 I refactored the code for overriding the OpenCensus implementation. There are two parts that I'm not sure about.
- CensusStatsModule no longer caches the StatsClientInterceptor and ServerTracerFactory. It creates a new object whenever getServerTracerFactory or getClientInterceptor is called. Is that correct?
- I'm not completely sure I used the right values for
recordStats
, especially in CensusModulesTest.
new CensusStatsModule(statsFactory, GrpcUtil.STOPWATCH_SUPPLIER, true, recordStats); | ||
tracerFactories.add(censusStats.getServerTracerFactory()); | ||
} | ||
Tagger tagger = this.tagger != null ? this.tagger : Tags.getTagger(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, are the three components coupled? For example, does one Tagger implementation only works with a certain StatsRecorder, or can they mix and match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Tagger and TagContextBinarySerializer objects are coupled. The StatsRecorder is independent, except that it also uses the gRPC Context key that is used by the tagging classes.
ef2fe43
to
404abba
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rebase.
build.gradle
Outdated
opencensus_impl: 'io.opencensus:opencensus-impl:0.7.0', | ||
opencensus_api: 'io.opencensus:opencensus-api:0.8.0', | ||
opencensus_contrib_grpc_metrics: 'io.opencensus:opencensus-contrib-grpc-metrics:0.8.0', | ||
opencensus_impl: 'io.opencensus:opencensus-impl:0.8.0', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you depend on the implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like it is only needed for the interop tests:
grpc-java/interop-testing/build.gradle
Line 29 in 37a67bf
runtime libraries.opencensus_impl |
decfbb0
to
95365c5
Compare
I rebased. I didn't squash any commits, so there is still a commit to upgrade to OpenCensus 0.8.0, even though that change was made on master. |
95365c5
to
1b464f6
Compare
"io.opencensus.contrib.grpc.metrics.RpcMeasureConstants" |
Okay to test. |
@ejona86 sorry for the wrong "contrib" name. We used it for "other" artifacts that are not in the core library. We will work in the future to maybe change that name. Thanks for the feedback, we are committed to keep backwards compatibility for "contrib" as well. |
Jenkins, retest this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM. Some minor comments.
@@ -61,15 +67,56 @@ | |||
} | |||
}; | |||
|
|||
private static final StatsContextFactory DUMMY_STATS_FACTORY = | |||
new StatsContextFactory() { | |||
private static final Tagger DUMMY_TAGGER = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably won't hurt if this test uses the fake implementations from StatsTestUtils. Then you can save a lot of lines of the dummy implementations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
private static final StatsContextFactory DUMMY_STATS_FACTORY = | ||
new StatsContextFactory() { | ||
|
||
private static final Tagger DUMMY_TAGGER = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
public static void setStatsContextFactory( | ||
AbstractManagedChannelImplBuilder<?> builder, StatsContextFactory factory) { | ||
builder.statsContextFactory(factory); | ||
public static void setStatsImplementation( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two methods should take the form of the corresponding methods in the builders.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -93,39 +107,29 @@ public long getMetricAsLongOrFail(MeasurementDescriptor metricName) { | |||
} | |||
|
|||
/** | |||
* This tag will be propagated by {@link FakeStatsContextFactory} on the wire. | |||
* This tag will be propagated by {@link FakeTagger} on the wire. | |||
*/ | |||
public static final TagKey EXTRA_TAG = TagKey.create("/rpc/test/extratag"); | |||
|
|||
private static final String EXTRA_TAG_HEADER_VALUE_PREFIX = "extratag:"; | |||
private static final String NO_EXTRA_TAG_HEADER_VALUE_PREFIX = "noextratag"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this and its related logic can be removed.
It was needed because the old StatsContext didn't provide a way to tell if it's empty, thus the metadata was always sent. Now that you have implemented the optimization to skip sending metdata if TagContext is empty, we should no longer need the metadata form that represents "no tag".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand. I didn't try to change any of the logic for serializing and deserializing tags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant if you remove this field and the if-branches that references this field, tests should not fail. Because of the following if
you added to CensusStatsModule
, those branches will never be executed now.
if (!module.tagger.empty().equals(parentCtx)) {
headers.put(module.statsHeader, parentCtx);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the optimization was added before this PR? This PR just changes the comparison to use tagger.empty()
instead of statsCtxFactory.getDefault()
.
I removed NO_EXTRA_TAG_HEADER_VALUE_PREFIX and the branches that used it, and the tests passed. It is the last commit. Shouldn't serialize
still handle the case where the TagContext isn't empty, but it doesn't contain EXTRA_TAG?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right ... the optimization was added before.
To keep it simple, FakeTagContextBinarySerializer
is supposed to only handle EXTRA_TAG
, and tests are supposed to only add EXTRA_TAG
. Now fromByteArray()
will fail if the metadata contains anything other than EXTRA_TAG
. toByteArray()
will fail too, by throwing NullPointerException -- it's probably better to make it throw UnsupportedOperationException
if extraTagValue==null
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made toByteArray throw an UnsupportedOperationException.
Yes it's correct. The caching wasn't necessary because it's only called per channel/server.
That sounds right. |
This commit updates gRPC core to use io.opencensus:opencensus-api and io.opencensus:opencensus-contrib-grpc-metrics instead of com.google.instrumentation:instrumentation-api for stats and tagging. The gRPC Monitoring Service continues to use instrumentation-api. The main changes affecting gRPC: - The StatsContextFactory is replaced by three objects, StatsRecorder, Tagger, and TagContextBinarySerializer. - The StatsRecorder, Tagger, and TagContextBinarySerializer are never null, but the objects are no-ops when the OpenCensus implementation is not available. This commit includes changes written by @songy23 and @sebright.
gRPC shouldn't use the state to determine whether to initialize the CensusStatsModule, because the state can be changed at runtime.
This commit adds a method to set the CensusStatsModule on AbstractServerImplBuilder and AbstractManagedChannelImplBuilder. It is simpler to set the whole CensusStatsModule than pass in all necessary OpenCensus implementation objects.
1b464f6
to
ca7ad9a
Compare
LGTM. Please merge master onto your branch and resolve the conflict. |
Thanks. I merged my branch. |
okay to test |
Thanks! |
Excellent! |
This commit updates gRPC core to use io.opencensus:opencensus-api and io.opencensus:opencensus-contrib-grpc-metrics instead of com.google.instrumentation:instrumentation-api for stats and tagging. The gRPC Monitoring Service continues to use instrumentation-api. The main changes affecting gRPC: - The StatsContextFactory is replaced by three objects, StatsRecorder, Tagger, and TagContextBinarySerializer. - The StatsRecorder, Tagger, and TagContextBinarySerializer are never null, but the objects are no-ops when the OpenCensus implementation is not available. This commit includes changes written by @songy23 and @sebright.
This commit updates gRPC core to use io.opencensus:opencensus-api and
io.opencensus:opencensus-contrib-grpc-metrics instead of
com.google.instrumentation:instrumentation-api for stats and tagging. The gRPC
Monitoring Service continues to use instrumentation-api.
The main changes affecting gRPC:
The StatsContextFactory is replaced by three objects, StatsRecorder, Tagger,
and TagContextBinarySerializer.
The StatsRecorder, Tagger, and TagContextBinarySerializer are never null,
but the objects are no-ops when the OpenCensus implementation is not
available.
This commit includes changes written by @songy23 and @sebright.
I added two TODOs for parts that I didn't know how to update. This PR is still using the snapshot of OpenCensus.
/cc @zhangkun83